#ifndef BINARIACPU_CU
#define BINARIACPU_CU

#include "binariaCPU.cuh"
#include "../fitness/binariaCPUFitness.cu"

/******************* Implementacion de Funciones del  *****************/

 void inicializarPoblacionBinariaCPU(bool* poblacion, float* fitnessActual, MersenneTwister *mt, int cantCromosomasPoblacion, float* fitnessOrdenadoHostCPU){
	//Obtengo posicion a escribir.
	int posicionCromosoma = 0;
	int posicionFitness = 0;

	for(int i = 0; i<cantGenesEnCromosoma * cantidadPoblacionesCPU * cantCromosomasPoblacion; i++){
		//Genero valor aleatorio.
		unsigned int r = (mt->genrand_int32()% 2);
		bool valor = (r == 1);
		poblacion[posicionCromosoma+i] = valor;
	}

	for(int i = 0; i< cantidadPoblacionesCPU * cantCromosomasPoblacion; i++){
		fitnessActual[posicionFitness] = calcularFitnessBinariaCPU(poblacion, posicionCromosoma);
		fitnessOrdenadoHostCPU[posicionFitness] = fitnessActual[posicionFitness];
		posicionFitness++;
		posicionCromosoma = posicionCromosoma + cantGenesEnCromosoma;
	}
}

 void mainKernelBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, float* fitnessActual, float* nuevoFitness, int * poblacionActualAcambiar, int *  nuevaPoblacionAcambiar, bool* individuosAMigrar, MersenneTwister *mt, int nroPoblacion, int posActual, bool *individuoAMigrarCPUaGPUhost,  float* fitnessOrdenado, int* vectorIndicesFitnessOrdenado, int iteracion, float* probabilidadRuleta, float* fitnessTotalParaRuleta){
	if(tipoSeleccion == 2){
		asignarProbabilidadRuletaBinariaCPU(fitnessActual, probabilidadRuleta, fitnessTotalParaRuleta, mt, nroPoblacion, posActual);
		if (posActual == cantCromosomasPoblacion/2 - 1){
			printf("total = %f\n", fitnessTotalParaRuleta[0]);
			for(int i=0;i<cantCromosomasPoblacion*cantidadPoblacionesCPU;i++){
				printf("** probabilidadRuleta ** i = %d prob = %f \n",i, probabilidadRuleta[i]);
			}
		}
	}
	int posicionCromosoma1 = seleccionBinariaCPU(fitnessActual, probabilidadRuleta, vectorIndicesFitnessOrdenado, mt, tipoSeleccion, nroPoblacion, posActual);
	int posicionCromosoma2 = seleccionBinariaCPU(fitnessActual, probabilidadRuleta, vectorIndicesFitnessOrdenado, mt, tipoSeleccion, nroPoblacion, posActual);

	cout<<"posicionCromosoma1 "<<posicionCromosoma1<<"\n";
	cout<<"posicionCromosoma2 "<<posicionCromosoma2<<"\n";
	cruzamientoRepresentacionBinariaCPU(poblacionActual, nuevaPoblacion, posicionCromosoma1, posicionCromosoma2, probabilidadCruzamiento, mt, tipoCruzamiento, nroPoblacion, posActual);

	mutacionBinariaCPU(nuevaPoblacion, probabilidadMutacion, mt, tipoMutacion, nroPoblacion, posActual);
	asignarFitnessBinariaCPU(nuevaPoblacion, nuevoFitness, nroPoblacion, posActual, fitnessOrdenado);
	reemplazoBinariaCPU(poblacionActual, nuevaPoblacion, poblacionActualAcambiar, nuevaPoblacionAcambiar, fitnessActual, nuevoFitness, tipoReemplazo, nroPoblacion, posActual);

	if ((iteracion + 1) % generacionesMigrar == 0) {
		if (posActual == cantCromosomasPoblacion/2 -1) {
			//si posActual(numero hilo) es el ultimo del bloque
			individuosAMigrarRepresentacionBinariaCPU(nuevoFitness, nuevaPoblacion, individuosAMigrar, nroPoblacion, posActual, individuoAMigrarCPUaGPUhost);
		}
	}
	//se pasa el individuo a migrar si hay al menos una poblacion en la gpu y soy la ultima poblacion de la cpu
}


/******************* Implementacion de Funciones de Migracion *****************/

 //Obtiene el mejor individuo de una poblacion (1 bloque por poblacion)
 //selecciona el mejor elemento
int obtenerMejorIndividuoBinaria(int nroPoblacion, float* vectorFitness){
	float mejor = INT_MIN;
	int indiceMejor;
	float valorFitness;
 	int indiceMemoria = nroPoblacion * cantCromosomasPoblacion;
 	for(int i = 0; i< cantCromosomasPoblacion; i++){
 		valorFitness = vectorFitness[indiceMemoria + i];
 		if (valorFitness > mejor) {
 			mejor = valorFitness;
 			indiceMejor = i;
 		}
 	}
 	int posicionCromosomaMejor = nroPoblacion * cantCromosomasPoblacion* cantGenesEnCromosoma+ indiceMejor * cantGenesEnCromosoma;
 	return posicionCromosomaMejor;
 }

 //Obtiene el indice del peor individuo y del fitness del peor individuo de una poblacion (1 bloque por poblacion) y retorna por referencia en el arreglo indices
 void obtenerPeorIndividuoBinaria(int nroPoblacion,float* vectorFitness, int indices[2]){
	float peor = INT_MAX;
 	int indicePeor;
 	float valorFitness;
 	int posicionCromosomaPeor;
 	int indiceMemoria = nroPoblacion * cantCromosomasPoblacion;
 	for(int i = 0; i< cantCromosomasPoblacion; i++){
 		valorFitness = vectorFitness[indiceMemoria + i];
 		if (valorFitness < peor) {
 			peor = valorFitness;
 			indicePeor = i;
 		}
 	}
 	posicionCromosomaPeor = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + indicePeor * cantGenesEnCromosoma;
 	indices[0] = posicionCromosomaPeor;
 	indices[1] = indicePeor;
 }

 void migracionRepresentacionBinariaCPU(bool* poblacionActual, float* fitnessActual, bool* individuosAMigrar, MersenneTwister *mt, bool* individuoAMigrarGPUaCPUhost){
	unsigned int r = mt->genrand_int32() % cantCromosomasPoblacion;
	int indices[2];
	int posicionCromosomaEmigrante;
	int posicionCromosomaInmigrante;
	int posicionFitness;
	int aux;
	for (int bloq = 0; bloq < cantidadPoblacionesCPU; bloq++) {

		if (bloq == 0) {
			aux = cantidadPoblacionesCPU - 1;
		} else {
			aux = (bloq - 1) % cantidadPoblacionesCPU;
		}
		posicionCromosomaInmigrante = aux * cantGenesEnCromosoma;
		obtenerPeorIndividuoBinaria(bloq, fitnessActual, indices);

		posicionCromosomaEmigrante = indices[0];
		if(bloq == 0 && cantidadPoblacionesGPU > 0){
			for (int i = 0; i<cantGenesEnCromosoma; i++) {
				poblacionActual[posicionCromosomaEmigrante + i] = individuoAMigrarGPUaCPUhost[i];
			}
		}else{
			for (int i = 0; i<cantGenesEnCromosoma; i++) {
				poblacionActual[posicionCromosomaEmigrante + i] = individuosAMigrar[posicionCromosomaInmigrante + i];
			}
		}
		posicionFitness = bloq * cantCromosomasPoblacion + indices[1];
		fitnessActual[posicionFitness] = calcularFitnessBinariaCPU(poblacionActual, posicionCromosomaEmigrante);
		printf("++++++++++++++++++++++++++ CPU ++++++++++++++++++++++++++++++++\n");
		printf("posicionFitness = %d \n", posicionFitness);
		printf("posicionCromosomaEmigrante = %d \n", posicionCromosomaEmigrante);
		printf("posicionCromosomaInmigrante = %d \n", posicionCromosomaInmigrante);
	}
}

 void individuosAMigrarRepresentacionBinariaCPU(float* nuevoFitness, bool* nuevaPoblacion, bool* individuosAMigrar, int nroPoblacion, int posActual, bool *individuoAMigrarCPUaGPUhost){
	int posicionMejorIndividuo = obtenerMejorIndividuoBinaria(nroPoblacion, nuevoFitness);
	cout <<"////////////////////nroPoblacion -> " <<nroPoblacion <<"\n";
	if(cantidadPoblacionesGPU > 0 && nroPoblacion == cantidadPoblacionesCPU-1){
		cout <<"/////////// entra acá ////////////\n";
		for (int i = 0; i<cantGenesEnCromosoma; i++) {
			individuoAMigrarCPUaGPUhost[i] = nuevaPoblacion[posicionMejorIndividuo + i];
		}
	}else{
		for (int i = 0; i<cantGenesEnCromosoma; i++) {
			individuosAMigrar[nroPoblacion*cantGenesEnCromosoma + i] = nuevaPoblacion[posicionMejorIndividuo + i];
		}
	}
}

 /******************* Implementacion de Funciones del  *****************/

void asignarProbabilidadRuletaBinariaCPU(float* fitnessActual, float* probabilidadRuletaBinaria, float* fitnessTotalParaRuleta,  MersenneTwister *mt, int nroPoblacion, int posActual){
	printf("*****asignarProbabilidadRuletaBinariaCPU******\n");
 	printf("posActual = %d\n",posActual);
 	printf("cantCromosomasPoblacion/2 - 1 = %d\n", cantCromosomasPoblacion/2 - 1);
 	if (posActual == 0){
 		fitnessTotalParaRuleta[nroPoblacion] = 0;
 		for (int i = nroPoblacion*cantCromosomasPoblacion; i < nroPoblacion*cantCromosomasPoblacion + cantCromosomasPoblacion; i++) {
 			fitnessTotalParaRuleta[nroPoblacion] += fitnessActual[i];
 		}

 		for (int i = nroPoblacion*cantCromosomasPoblacion; i < nroPoblacion*cantCromosomasPoblacion + cantCromosomasPoblacion; i++) {
 			probabilidadRuletaBinaria[i] = fitnessActual[i]/fitnessTotalParaRuleta[nroPoblacion] * 100;
 		}
 	}
}

/******************* Implementacion de Funciones de Selecccion *****************/

 int seleccionBinariaCPU(float* vectorFitness, float* probabilidadRuleta, int* vectorIndicesFitnessOrdenado, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual){
	int resultado = -1;
	if(ejecutarFuncion == 0) {
		resultado = seleccionPorRangoBinariaCPU(vectorIndicesFitnessOrdenado, mt, nroPoblacion, posActual);
	}
	else{
		if(ejecutarFuncion == 1){
			resultado = seleccionPorTorneoBinariaCPU(vectorFitness, mt, nroPoblacion, posActual);
		}
		else {
			if(ejecutarFuncion == 2) {
				resultado = seleccionRuedaRuletaBinariaCPU(probabilidadRuleta, mt, nroPoblacion, posActual);
			}
		}
	}
	return resultado;
}


//Seleccion por torneo
//selecciona 2 individuos al azar y devuelve la posicion del mejor
 int seleccionPorTorneoBinariaCPU(float* vectorFitness, MersenneTwister *mt, int nroPoblacion, int posActual){
	//printf("*** Seleccion por torneo ***\n");
	unsigned int r = mt->genrand_int32()% cantCromosomasPoblacion;
	int posicionFitnessAleatoria1 = nroPoblacion * cantCromosomasPoblacion + r;
	int posicionCromosomaAleatoria1 = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + r * cantGenesEnCromosoma;
	r = mt->genrand_int32()% cantCromosomasPoblacion;
	int posicionFitnessAleatoria2 = nroPoblacion * cantCromosomasPoblacion + r;
	int posicionCromosomaAleatoria2 = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + r * cantGenesEnCromosoma;
	if (vectorFitness[posicionFitnessAleatoria1] > vectorFitness[posicionFitnessAleatoria2])
		return posicionCromosomaAleatoria1;
	return posicionCromosomaAleatoria2;
}

//Seleccion por rango
 int seleccionPorRangoBinariaCPU(int* vectorIndicesFitnessOrdenado, MersenneTwister *mt, int nroPoblacion, int posActual){
	//printf("*** Seleccion por rango ***\n");
	unsigned int indiceMejor =  mt->genrand_int32()% cantidadIndividuosSeleccionPorRango;
	printf("indiceMejor = %d\n", indiceMejor);
	printf("vectorIndicesFitnessOrdenado[blockIdx.y * cantCromosomasPoblacion + indiceMejor] = %d\n", vectorIndicesFitnessOrdenado[nroPoblacion * cantCromosomasPoblacion + indiceMejor]);

	int posicionCromosoma = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + vectorIndicesFitnessOrdenado[nroPoblacion * cantCromosomasPoblacion + indiceMejor] * cantGenesEnCromosoma;
	return posicionCromosoma;
}

 //Seleccion por rueda de ruleta
int seleccionRuedaRuletaBinariaCPU(float* probabilidadRuleta, MersenneTwister *mt, int nroPoblacion, int posActual){
 	float aux =  mt->genrand_int32();
 	float r = fmod(aux, 100);
 	printf("r, %f\n", r);
 	float suma = probabilidadRuleta[nroPoblacion*cantCromosomasPoblacion];
 	printf("suma %f\n", suma);
 	int i = 0;
 	while(r>suma){
 		i++;
 		suma = suma + probabilidadRuleta[nroPoblacion * cantCromosomasPoblacion + i];
 	}
 	printf("i %d\n", i);
 	int posicionCromosoma = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + i * cantGenesEnCromosoma;
 	return posicionCromosoma;
}

/******************* Implementacion de Funciones de Cruzamiento *****************/

 void cruzamientoRepresentacionBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual){

	if(ejecutarFuncion == 0) {
		cruzamientoCromosoma1PuntoBinariaCPU(poblacionActual, nuevaPoblacion, posicionCromosoma1, posicionCromosoma2, probabilidad, mt, nroPoblacion, posActual);
	}
	else{
		if(ejecutarFuncion == 1){
			cruzamientoCromosoma2PuntosBinariaCPU(poblacionActual, nuevaPoblacion, posicionCromosoma1, posicionCromosoma2, probabilidad, mt, nroPoblacion, posActual);
		}
		else {
			if(ejecutarFuncion == 2) {
				cruzamientoCromosomaUniformeBinariaCPU(poblacionActual, nuevaPoblacion, posicionCromosoma1, posicionCromosoma2, probabilidad, mt, nroPoblacion, posActual);
			}
		}
	}
}

//Se selecciona un punto de corte y se intercambian los genes de los padres para formar los hijos
 void cruzamientoCromosoma1PuntoBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual){
	//printf("*** Cruzamiento 1Punto ***\n");
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * totalGenesEnPoblacion;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;
	//printf("posicionCromosoma1  %d\n", posicionCromosoma1);
	//printf("posicionCromosoma2  %d\n", posicionCromosoma2);

	unsigned int prob = (mt->genrand_int32() % 101);
	if (prob < probabilidad){
		unsigned int r = mt->genrand_int32() % cantGenesEnCromosoma;
		//printf("r %d\n", r);
		for(int i=0; i<cantGenesEnCromosoma; i++){
			if(i<=r){
				nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
				nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
			}else{
				nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma2 + i];
				nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma1 + i];
			}
		}
	}else{
		for(int i=0; i<cantGenesEnCromosoma; i++){
			nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
		}
	}
}

//Se seleccionan 2 puntos de corte y se intercambian los genes de los padres para formar los hijos
 void cruzamientoCromosoma2PuntosBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual){
	printf("*** Cruzamiento 2Puntos ***\n");
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * totalGenesEnPoblacion;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;
	unsigned int prob = (mt->genrand_int32() % 101);
	if (prob < probabilidad){
		unsigned int r1 = mt->genrand_int32() % cantGenesEnCromosoma;
		unsigned int r2 = mt->genrand_int32() % cantGenesEnCromosoma;
		printf("r1 %d\n", r1);
		printf("r2 %d\n", r2);

		int i = 0;
		while(r2 == r1){
			r2 = (mt->genrand_int32() + 1) % cantGenesEnCromosoma;
			i++;
		}

		if(r2<r1){
			unsigned int r3 = r1;
			r1 = r2;
			r2 = r3;
		}

		for(int i=0; i<cantGenesEnCromosoma; i++){
			if(i<r1){
				nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
				nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
			}else if(i<=r2){
				nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma2 + i];
				nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma1 + i];
			}else{
				nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
				nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
			}
		}
	}else{
		for(int i=0; i<cantGenesEnCromosoma; i++){
			nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
		}
	}
}


//en cada posición de los progenitores se decide intercambiar el valor
//genético de cada punto de acuerdo a una probabilidad prefijada
 void cruzamientoCromosomaUniformeBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual){
	printf("*** Cruzamiento Uniforme ***\n");
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * totalGenesEnPoblacion;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;
	printf("posicionNuevoCromosoma1  %d\n", posicionNuevoCromosoma1);
	printf("posicionNuevoCromosoma2  %d\n", posicionNuevoCromosoma2);

	unsigned int prob;
	for(int i=0; i<cantGenesEnCromosoma; i++){
		prob = (mt->genrand_int32() % 101);
		if(prob < probabilidad ){
			printf("i = %d", i);
			nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma2 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma1 + i];
		}
		else {
			nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma1 + i];
			nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma2 + i];
		}
	}
}


/******************* Implementacion de Funciones de Mutacion *****************/

 void mutacionBinariaCPU(bool* poblacion, float probabilidad, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual){
	if(ejecutarFuncion == 0) {
		mutacionPorInversion(poblacion, probabilidad, mt, nroPoblacion, posActual);
	}
}

//Mutacion por inversion del valor del alelo
//Se modifica aleatoriamente (con probabilidad ''probabilidad') uno de los valores binarios del cromosoma
 void mutacionPorInversion(bool* poblacion, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual){
	//printf("*** Mutacion por inversion ***\n");
	unsigned int r;
	int posicionNuevoCromosoma1 = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma;
	int posicionNuevoCromosoma2 = posicionNuevoCromosoma1 + cantGenesEnCromosoma;
	if((mt->genrand_int32() % 101) >= probabilidad ){
		r = (mt->genrand_int32() % cantGenesEnCromosoma);
		//printf("r  %d\n", r);
		if(poblacion[posicionNuevoCromosoma1+r] == 0)
			poblacion[posicionNuevoCromosoma1+r] = 1;
		else
			poblacion[posicionNuevoCromosoma1+r] = 0;
	}
	if((mt->genrand_int32() % 101) >= probabilidad ){
		r = (mt->genrand_int32() % cantGenesEnCromosoma);
		//printf("r  %d\n", r);
		if(poblacion[posicionNuevoCromosoma2+r] == 0)
			poblacion[posicionNuevoCromosoma2+r] = 1;
		else
			poblacion[posicionNuevoCromosoma2+r] = 0;
	}
}



/******************* Implementacion de Funciones de fitness *****************/

void asignarFitnessBinariaCPU(bool* nuevaPoblacion, float* nuevoVectorFitness, int nroPoblacion, int posActual, float* fitnessOrdenado){
 	//Obtengo posicion del primer cromosoma.
 	int posicionCromosoma = posActual * cantGenesEnCromosoma * 2 + nroPoblacion * totalGenesEnPoblacion;
 	int posicionFitness = posActual * 2 + nroPoblacion * cantCromosomasPoblacion;
 	nuevoVectorFitness[posicionFitness] = calcularFitnessBinariaCPU(nuevaPoblacion, posicionCromosoma);
 	nuevoVectorFitness[posicionFitness + 1] = calcularFitnessBinariaCPU(nuevaPoblacion, posicionCromosoma + cantGenesEnCromosoma);

 	fitnessOrdenado[posicionFitness] = nuevoVectorFitness[posicionFitness];
 	fitnessOrdenado[posicionFitness + 1] = nuevoVectorFitness[posicionFitness + 1];
 }


 /******************** Implementacion de Funciones de reemplazo **************/

void reemplazoBinariaCPU(bool * poblacionActual, bool * nuevaPoblacion, int * poblacionActualAcambiar, int * nuevaPoblacionAcambiar, float * fitnessActual, float* nuevoFitness, int ejecutarFuncion, int nroPoblacion, int posActual){
 	if(ejecutarFuncion == 1) {
 		reemplazoElitistaBinariaCPU(poblacionActual, nuevaPoblacion, poblacionActualAcambiar, nuevaPoblacionAcambiar, fitnessActual, nuevoFitness, nroPoblacion, posActual);
 	}
 }

void reemplazoElitistaBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int* poblacionActualAcambiar, int* nuevaPoblacionAcambiar, float * fitnessActual, float* nuevoFitness, int nroPoblacion, int posActual){
 	printf("*****reemplazo Elitista Binaria CPU******\n");
 	printf("posActual = %d\n",posActual);
 	printf("nroPoblacion + cantCromosomasPoblacion/2 - 1 = %d\n", cantCromosomasPoblacion/2 - 1);
 	if (posActual == cantCromosomasPoblacion/2 - 1){
 		int cantAremplazar = (int) (porcentajeElitismo * cantCromosomasPoblacion / 100);
 		float peor = INT_MAX;
 		float mejor = INT_MIN;
 		int posPeor = -1;
 		int posMejor = -1;
 		int posFitness = nroPoblacion * cantCromosomasPoblacion;
 		for (int i = 0; i < cantAremplazar; i++){
 			if (fitnessActual[posFitness + i] < peor) {
 				peor = fitnessActual[posFitness + i];
 				posPeor = i;
 			}

 			if (nuevoFitness[posFitness + i] > mejor) {
 				mejor = nuevoFitness[posFitness + i];
 				posMejor = i;
 			}

 			poblacionActualAcambiar[posFitness + i] = 1;
 			nuevaPoblacionAcambiar[posFitness + i] = 1;
 		}

 		printf("peor = %d\n",peor);
 		printf("mejor = %d\n",mejor);

 		for (int i = cantAremplazar; i < cantCromosomasPoblacion; i++){
 			if (fitnessActual[posFitness + i] > peor) {
 				poblacionActualAcambiar[posFitness + i] = 1;
 				poblacionActualAcambiar[posFitness + posPeor] = 0;
 				peor = INT_MAX;
 				posPeor = -1;
 				for (int j = 0; j <= i; j++){
 					if (poblacionActualAcambiar[posFitness + j] == 1) {
 						if (fitnessActual[posFitness + j] < peor) {
 							peor = fitnessActual[posFitness + j];
 							posPeor = j;
 						}
 					}
 				}
 			}
 			else {
 				poblacionActualAcambiar[posFitness + i] = 0;
 			}

 			if (nuevoFitness[posFitness + i] < mejor) {
 				nuevaPoblacionAcambiar[posFitness + i] = 1;
 				nuevaPoblacionAcambiar[posFitness + posMejor] = 0;
 				mejor = INT_MIN;
 				posMejor = -1;
 				for (int j = 0; j <= i; j++) {
 					if (nuevaPoblacionAcambiar[posFitness + j] == 1) {
 						if (nuevoFitness[posFitness + j] > mejor) {
 							mejor = nuevoFitness[posFitness + j];
 							posMejor = j;
 						}
 					}
 				}
 			}
 			else {
 				nuevaPoblacionAcambiar[posFitness + i] = 0;
 			}
 		}

 		for (int i = posFitness; i < posFitness + cantCromosomasPoblacion; i++){
			printf("poblacionActualAcambiar[%d] = %d\n",i,poblacionActualAcambiar[i]);
			//cuPrintf("nuevaPoblacionAcambiar[%d] = %d\n",i,nuevaPoblacionAcambiar[i]);
		}
		for (int i = posFitness; i < posFitness + cantCromosomasPoblacion; i++){
			//cuPrintf("poblacionActualAcambiar[%d] = %d\n",i,poblacionActualAcambiar[i]);
			printf("nuevaPoblacionAcambiar[%d] = %d\n",i,nuevaPoblacionAcambiar[i]);
		}

 		for (int i = 0; i < cantAremplazar; i++) {
 			int j = 0;
 			while (poblacionActualAcambiar[posFitness + j] == 0) {
 				j++;
 			}

 			int k = 0;
 			while (nuevaPoblacionAcambiar[posFitness + k] == 0) {
 				k++;
 			}

 			nuevoFitness[posFitness + k] = fitnessActual[posFitness + j];
 			int posNuevoCromosoma = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + k * cantGenesEnCromosoma;
 			int posCromosomaActual = nroPoblacion * cantCromosomasPoblacion * cantGenesEnCromosoma + j * cantGenesEnCromosoma;
 			for (int h = 0; h < cantGenesEnCromosoma; h++) {
 				nuevaPoblacion[posNuevoCromosoma + h] = poblacionActual[posCromosomaActual + h];
 			}
 			poblacionActualAcambiar[posFitness + j] = 0;
 			nuevaPoblacionAcambiar[posFitness + k] = 0;
 		}
 	}
 }
/******************* Implementacion de Funciones del host *****************/


void imprimirBinariaCPU(float* fitnessHost, int tamVectorFitness, bool* poblacionHost, int tamVectorPoblacion, int iteracion){
 	cout << "\nPOBLACION ITERACION "<< iteracion<<" CPU\n";
 	for (int i = 0; i<totalGenesCPU; i++){
 		if(i%cantGenesEnCromosoma == 0){
 			cout << "\n";

 		}
 		printf("%i ", poblacionHost[i]);
 	}
 	cout << "\n\n\nFITNESS CPU\n";

 	for (int i = 0; i<cantCromosomasPoblacion * cantidadPoblacionesCPU; i++){
 		printf("%f ", fitnessHost[i]);
 	}
 	cout << "\n\n\n\n";
}

void representacionBinariaCPU(bool *poblacionActualHost, bool *nuevaPoblacionHost, float* fitnessActualHost, float *nuevoFitnessHost,int * poblacionActualAcambiar, int *  nuevaPoblacionAcambiar, bool * individuosAMigrarHostCPU, MersenneTwister* mt, int iteracion, int tamVectorPoblacion, int tamVectorFitness, bool *individuoAMigrarCPUaGPUhost, float* fitnessOrdenadoHostCPU, int* indicesFitnessOrdenadoHostCPU, float* probabilidadRuletaHostCPU, float* fitnessTotalParaRuletaHostCPU) {
	int nroPoblacion = 0;
	for (int i = 0; i < cantidadPoblacionesCPU*cantCromosomasPoblacion/2; i++){
		nroPoblacion = i/(cantCromosomasPoblacion/2);
		if ((iteracion % 2) == 0) {
			mainKernelBinariaCPU(poblacionActualHost, nuevaPoblacionHost, fitnessActualHost, nuevoFitnessHost, poblacionActualAcambiar, nuevaPoblacionAcambiar, individuosAMigrarHostCPU, mt, nroPoblacion, i%(cantCromosomasPoblacion/2), individuoAMigrarCPUaGPUhost, fitnessOrdenadoHostCPU, indicesFitnessOrdenadoHostCPU, iteracion, probabilidadRuletaHostCPU, fitnessTotalParaRuletaHostCPU);
		} else {
			mainKernelBinariaCPU(nuevaPoblacionHost, poblacionActualHost, nuevoFitnessHost, fitnessActualHost, poblacionActualAcambiar, nuevaPoblacionAcambiar, individuosAMigrarHostCPU, mt, nroPoblacion,  i%(cantCromosomasPoblacion/2), individuoAMigrarCPUaGPUhost, fitnessOrdenadoHostCPU, indicesFitnessOrdenadoHostCPU, iteracion, probabilidadRuletaHostCPU, fitnessTotalParaRuletaHostCPU);
		}
	}

	//Imprimo solo en la ultima iteracion o si esta en modo debug imprimo siempre
	if ((iteracion == numeroGeneraciones - 1) || (modoDebug == 1)) {
		if ((iteracion % 2) == 0) {
			imprimirBinariaCPU(nuevoFitnessHost, tamVectorFitness, nuevaPoblacionHost, tamVectorPoblacion, iteracion);
		} else {
			imprimirBinariaCPU(fitnessActualHost, tamVectorFitness, poblacionActualHost, tamVectorPoblacion, iteracion);
		}
	}
}

#endif
